package com.xsqf.jt808.netty.server;

import com.xsqf.jt808.common.codec.JT808Decoder;
import com.xsqf.jt808.common.codec.JT808Encoder;
import com.xsqf.jt808.common.config.JT808Const;
import com.xsqf.jt808.netty.handler.*;
import com.xsqf.jt808.netty.handler.*;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.EventExecutorGroup;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @ClassName: NettyListenServer
 * @Description:
 * @Author:
 * @Date: 2020/5/6 17:40
 * @Version: v1.0.0
 */
@Slf4j
@Component
@Qualifier(value = "nettyListenServer")
public class NettyListenServer {

    @Value("${netty.read-timeout}")
    private int readTimeOut;

    @Autowired
    @Qualifier("businessGroup")
    private EventExecutorGroup businessGroup;

    @Autowired
    private AuthMsgHandler authMsgHandler;

    @Autowired
    private HeartBeatMsgHandler heartBeatMsgHandler;

    @Autowired
    private LocationMsgHandler locationMsgHandler;

    @Autowired
    private LogOutMsgHandler logOutMsgHandler;

    @Autowired
    private RegisterMsgHandler registerMsgHandler;

    @Autowired
    private PositionHandler positionHandler;

    @Autowired
    private TerminalComRespHandler terminalComRespHandler;

    public void start(final int port) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());
                            ch.pipeline().addLast(
                                    new IdleStateHandler(readTimeOut, 0, 0, TimeUnit.MINUTES))
                                    .addLast(new DelimiterBasedFrameDecoder(1100, Unpooled.copiedBuffer(new byte[]{JT808Const.PKG_DELIMITER})))
                                    .addLast(new JT808Decoder())
                                    .addLast(new JT808Encoder())
                                    .addLast(heartBeatMsgHandler)
                                    .addLast(businessGroup, locationMsgHandler) ////因为locationMsgHandler中涉及到数据库操作，所以放入businessGroup
                                    .addLast(authMsgHandler)
                                    .addLast(registerMsgHandler)
                                    .addLast(logOutMsgHandler)
                                    .addLast(positionHandler)
                                    .addLast(terminalComRespHandler);
                        }
                    }).option(ChannelOption.SO_BACKLOG, 1024)
                    .childOption(ChannelOption.TCP_NODELAY, true)//立即写出
                    .childOption(ChannelOption.SO_KEEPALIVE, true);
            ChannelFuture future = b.bind(port).sync();
            if (future.isSuccess()) {
                log.info("TCP服务启动完毕,port={}", port);
            }
            future.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

}
